﻿#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion

using System;
using System.Globalization;
using Newtonsoft.Utilities.Text;
using NUnit.Framework;

namespace Newtonsoft.Utilities.Tests.Text
{
  public class StringExtensionsTests : TestsBase
  {
    [Test]
    public void FormatWithNamed()
    {
      var o = new
      {
        Name = "TheName",
        Age = 12,
        BirthDate = new DateTime(2000, 12, 20),
        Dad = new
        {
          Name = "DadName"
        },
        Results = new[]
        {
          new { Name = "INFO", Grade = 10 },
          new { Name = "ECLM", Grade = 9 }
        }
      };

      Assert.AreEqual("{TheName} - 12 - 2000-12-20T00:00:00.0000000 - DadName",
        "{{{Name}}} - {Age} - {BirthDate:o} - {Dad.Name}".FormatWith(o));

      Assert.AreEqual("INFO - 10, ECLM - 9",
        "{Results[0].Name} - {Results[0].Grade}, {Results[1].Name} - {Results[1].Grade}".FormatWith(o));

      Assert.AreEqual("5", "{Length}".FormatWith("12345"));

      Assert.AreEqual("20/12/2000 12:00:00 a.m.", "{BirthDate}".FormatWith(CultureInfo.GetCultureInfo("en-NZ"), o));

      Assert.AreEqual("12/20/2000 12:00:00 AM", "{BirthDate}".FormatWith(CultureInfo.GetCultureInfo("en-US"), o));

      //MembershipUser user = Membership.GetUser();

      //Status.Text = "{UserName} last logged in at {LastLoginDate:S}".FormatWith(user);

      //Process p = new Process();
      //p.ProcessName

      //"{CurrentTime} - {ProcessName}".FormatWith(new { CurrentTime = DateTime.Now, ProcessName = p.ProcessName });

      var student = new
      {
        Name = "John",
        Email = "john@roffle.edu",
        BirthDate = new DateTime(1983, 3, 20),
        Results = new[]
        {
          new { Name = "COMP101", Grade = 10 },
          new { Name = "ECON101", Grade = 9 }
        }
      };

      Console.WriteLine("Top result for {Name} was {Results[0].Name}".FormatWith(student));
      // "Top result for John was INFO101"

      Assert.AreEqual("Top result for John was COMP101", "Top result for {Name} was {Results[0].Name}".FormatWith(student));
    }

    [Test]
    public void FormatWithPosition()
    {
      var o = new
      {
        Name = "TheName",
        Age = 12,
        BirthDate = new DateTime(2000, 12, 20),
        Dad = new
        {
          Name = "DadName"
        },
        Results = new[]
        {
          new { Name = "INFO", Grade = 10 },
          new { Name = "ECLM", Grade = 9 }
        }
      };

      Assert.AreEqual("{TheName}", "{{{0}}}".FormatWith(o.Name));

      Assert.AreEqual("{TheName} - 12 - 2000-12-20T00:00:00.0000000 - DadName",
        "{{{0}}} - {1} - {2:o} - {3}".FormatWith(o.Name, o.Age, o.BirthDate, o.Dad.Name));

      Assert.AreEqual("20/12/2000 12:00:00 a.m.", "{0}".FormatWith(CultureInfo.GetCultureInfo("en-NZ"), o.BirthDate));

      Assert.AreEqual("12/20/2000 12:00:00 AM", "{0}".FormatWith(CultureInfo.GetCultureInfo("en-US"), o.BirthDate));

      Assert.AreEqual("{12/20/2000 12:00:00 AM", "{{{0}".FormatWith(CultureInfo.GetCultureInfo("en-US"), o.BirthDate));

      Assert.AreEqual(string.Format("", new object[] { }), "".FormatWith(new object[] { }));
    }

    #region Truncate
    [Test]
    public void TruncateTest()
    {
      string truncatedText;

      truncatedText = "The quick brown fox jumped over the lazy dog.".Truncate(20);

      Assert.AreEqual("The quick brown f...", truncatedText);

      truncatedText = "The quick brown fox jumped over the lazy dog.".Truncate(20, "-");

      Assert.AreEqual("The quick brown fox-", truncatedText);

      truncatedText = "The quick brown fox jumped over the lazy dog.".Truncate(45);

      Assert.AreEqual("The quick brown fox jumped over the lazy dog.", truncatedText);

      truncatedText = "The quick brown fox jumped over the lazy dog.".Truncate(44);

      Assert.AreEqual("The quick brown fox jumped over the lazy...", truncatedText);
    }

    [Test]
    [ExpectedException(typeof(ArgumentException), ExpectedMessage = @"Maximum length must be greater than zero.
Parameter name: maximumLength")]
    public void TruncateMaximumLengthTest()
    {
      "The quick brown fox jumped over the lazy dog.".Truncate(-5);
    }
    #endregion

    #region IsWhiteSpace
    [Test]
    public void IsWhiteSpaceTest()
    {
      bool result = (@"  
" + StringUtils.Tab + @"
").IsWhiteSpace();

      Assert.IsTrue(result);

      result = (@" 
" + StringUtils.Tab + "  s  ").IsWhiteSpace();

      Assert.IsFalse(result);
    }

    [Test]
    [ExpectedException(typeof(ArgumentNullException), ExpectedMessage = @"Value cannot be null.
Parameter name: s")]
    public void IsWhiteSpaceNullTest()
    {
      ((string)null).IsWhiteSpace();
    }
    #endregion

    #region HasWhiteSpace
    [Test]
    public void HasWhiteSpaceTest()
    {
      bool result = (@"  
" + StringUtils.Tab + @"
").HasWhiteSpace();

      Assert.IsTrue(result);

      result = (@" 
" + StringUtils.Tab + "  s  ").HasWhiteSpace();

      Assert.IsTrue(result);

      result = string.Empty.IsWhiteSpace();

      Assert.IsFalse(result);

      result = "Pie".IsWhiteSpace();

      Assert.IsFalse(result);
    }

    [Test]
    [ExpectedException(typeof(ArgumentNullException), ExpectedMessage = @"Value cannot be null.
Parameter name: s")]
    public void HasWhiteSpaceNullTest()
    {
      ((string)null).HasWhiteSpace();
    }
    #endregion

    #region EnsureEndsWith
    [Test]
    public void EnsureEndsWithTest()
    {
      string result;

      result = "Pie".EnsureEndsWith(".");

      Assert.AreEqual("Pie.", result);

      result = "Pie.".EnsureEndsWith(".");

      Assert.AreEqual("Pie.", result);

      result = "Pie. ".EnsureEndsWith(".");

      Assert.AreEqual("Pie. ", result);

      result = "Pie. ".EnsureEndsWith(". ");

      Assert.AreEqual("Pie. ", result);

      result = "Pie. ".EnsureEndsWith(";");

      Assert.AreEqual("Pie. ;", result);

      result = "Pie. ".EnsureEndsWith(string.Empty);

      Assert.AreEqual("Pie. ", result);
    }

    [Test]
    [ExpectedException(typeof(ArgumentNullException), ExpectedMessage = "Value cannot be null." + StringUtils.CarriageReturnLineFeed + "Parameter name: target")]
    public void EnsureEndsWithTargetNullTest()
    {
      ((string)null).EnsureEndsWith(".");
    }

    [Test]
    [ExpectedException(typeof(ArgumentNullException), ExpectedMessage = "Value cannot be null." + StringUtils.CarriageReturnLineFeed + "Parameter name: value")]
    public void EnsureEndsWithValueNullTest()
    {
      "Pie.".EnsureEndsWith(null);
    }
    #endregion

    #region Indent
    [Test]
    public void IndentTest()
    {
      string result;

      result = @"The quick brown
fox jumps over
the lazy dog.".Indent(4);

      Assert.AreEqual(@"    The quick brown
    fox jumps over
    the lazy dog.", result);

      result = @"The quick brown
fox jumps over
the lazy dog.".Indent(1, StringUtils.Tab);

      Assert.AreEqual(@"	The quick brown
	fox jumps over
	the lazy dog.", result);
    }

    [Test]
    [ExpectedException(typeof(ArgumentNullException), ExpectedMessage = "Value cannot be null." + StringUtils.CarriageReturnLineFeed + "Parameter name: s")]
    public void IndentStringNullTest()
    {
      ((string)null).Indent(1);
    }

    [Test]
    [ExpectedException(typeof(ArgumentException), ExpectedMessage = "Must be greater than zero." + StringUtils.CarriageReturnLineFeed + "Parameter name: indentation")]
    public void IndentIndentationLessThanZeroTest()
    {
      "Pie.".Indent(-1);
    }
    #endregion

    #region Indent
    [Test]
    public void NumberLines()
    {
      string result;

      result = @"The
quick
brown
fox
jumps
over
the
lazy
dog
.".NumberLines();

      Assert.AreEqual(@"   1. The
   2. quick
   3. brown
   4. fox
   5. jumps
   6. over
   7. the
   8. lazy
   9. dog
  10. .", result);
    }

    [Test]
    [ExpectedException(typeof(ArgumentNullException), ExpectedMessage = "Value cannot be null." + StringUtils.CarriageReturnLineFeed + "Parameter name: s")]
    public void NumberLinesNullTest()
    {
      ((string)null).Indent(1);
    }
    #endregion
  }
}
